#include "heaptimer.h"
void HeapTime::sifup_(size_t i) //上滤
{
    assert(i<Heap_.size());
    int parent_i = (i-1)/2;
    while(parent_i >=0)
    {
        if(Heap_.at(i) < Heap_.at(parent_i))
        {
            swap_node(i,parent_i);
            i =parent_i;
            parent_i = (i-1)/2;
        }
        else
        {
            break;
        }
    } 

}
bool HeapTime::sifdown_(size_t i,size_t n)
{
    assert(i< Heap_.size());
    assert(n<= Heap_.size());
    size_t index = i;
    size_t child = (2*index)+1;
    //如果 index 结点 为父节点
    while(child < n)
    {
        if((child +1)<n && Heap_.at(child) > Heap_.at(child+1))
        {
            child +=1;
        }
        if(Heap_.at(child) < Heap_.at(index))
        {
            swap_node(child,index);
            index = child;
            child = (2*index)+1;
        }
        else
        {
            break;
        }
    }
    return index >i;
    //true 为下虑成功,false失败
}
void HeapTime::swap_node(size_t i,size_t j)
{
    assert(i< Heap_.size());
    assert(j< Heap_.size());
    //交换地址,ref_也会牵涉到
    std::swap(Heap_[i],Heap_[j]);
    //还原ref_
    ref_[Heap_[i].id] = i;
    ref_[Heap_[j].id] = j;
}
void HeapTime::del_(size_t i)
{
    assert(i<Heap_.size());
    size_t index = i;
    size_t n = Heap_.size() -1;
    assert(index <= n);
    if(index < n)
    {
        swap_node(i,n);
        if(sifdown_(index,n) == false)
        {
            sifup_(index);
        }
    }
    ref_.erase(Heap_.back().id);
    Heap_.pop_back();
    
}
void HeapTime::add(int id,int timeout,const TimeCallBack& cb)
{
    assert(id>=0);
    if(ref_.count(id)!=0)
    {//变时操作
        int temp = ref_[id];
        //这里的timeout 有可能会 <0 ？
        Heap_[temp].expires = Clock::now() + MS(timeout);
        Heap_[temp].cb = cb;
        //进行堆排序
        //下滤失败表示该结点的增大仍未破坏该节点构成的小顶堆
        //只能考虑上滤
        if(sifdown_(temp,Heap_.size()) == false)
            sifup_(temp);
    }
    else
    {//原地构造一个
        size_t n = Heap_.size();
        ref_[id] = n;
        Heap_.push_back({id,cb,Clock::now() + MS(timeout)});
        Heap_.emplace_back(id,cb,Clock::now() + MS(timeout));
        sifup_(n);
    }
}
void HeapTime::adjust(int id,int newExpires)
{
    assert(Heap_.empty()==false && ref_.count(id)!=0);
    //加时
    Heap_[ref_[id]].expires = Clock::now() + MS(newExpires);
    sifdown_(ref_[id],Heap_.size());
}
void HeapTime::doWork(int id)
{
    if(Heap_.empty()==false ||ref_.count(id)==0)
    {
        return;
    }
    size_t i = id;
    auto node = Heap_.at(i);
    node.cb();
    del_(i);
}
void HeapTime::tick()
{
    if(Heap_.empty() == true)
    {
        return ;
    }
    while(Heap_.empty()==false)
    {
        TimerNode temp = Heap_.front();
        if(std::chrono::duration_cast<MS>(temp.expires - Clock::now()).count() > 0)
        {//未超时
            break;
        }
        temp.cb();
        pop();
    }
}
int HeapTime::GetNetTick()
{
    tick();
    int res = -1;
    if(Heap_.empty() == false)
    {
        res = std::chrono::duration_cast<MS>(Heap_.front().expires - Clock::now()).count();
        if(res <0 ) {   res = 0; }
    }
    return res;
}
void HeapTime::pop()
{
    //删除堆顶定时器
    assert(Heap_.empty()==false);
    del_(0);
}
void HeapTime::clear()
{
    Heap_.clear();
    ref_.clear();
}